/*
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 * http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * htap_logger.h
 * Holds global configuration for the HTAP module.
 *
 * IDENTIFICATION
 * src/include/storage/htap/htap_logger.h
 *
 * -------------------------------------------------------------------------
 */

#ifndef HTAP_LOGGER_H
#define HTAP_LOGGER_H

#include <cstdarg>
#include "log_level.h"
#include "mot_log.h"
#include "logger.h"
#include "log_level_formatter.h"
#include "mot_error.h"
#include "htap_global.h"
#include "utils/be_module.h"

//  adapt all names to HTAP naming convention
namespace htap {
using LogLevel = MOT::LogLevel;
using Logger = MOT::Logger;

/* * @define DECLARE_LOGGER Use this macro to declare a logger at a source file. */
#define HTAP_DECLARE_LOGGER(LoggerName, ComponentName) DECLARE_LOGGER(LoggerName, ComponentName)

/* * @define DECLARE_CLASS_LOGGER Use this macro to declare a logger at a class level in its header file. */
#define HTAP_DECLARE_CLASS_LOGGER() DECLARE_CLASS_LOGGER()

/* * @define IMPLEMENT_CLASS_LOGGER Use this macro to define the class logger at its source file. */
#define HTAP_IMPLEMENT_CLASS_LOGGER(Class, Component) IMPLEMENT_CLASS_LOGGER(Class, Component)

/* * @define IMPLEMENT_TEMPLATE_LOGGER Use this macro to define a class logger declared in a template class. */
#define HTAP_IMPLEMENT_TEMPLATE_LOGGER(Class, Component) IMPLEMENT_TEMPLATE_LOGGER(Class, Component)

/* * @define LOGGER_FULL_NAME The full name of the current logger as it would appear in the log file. */
#define HTAP_LOGGER_FULL_NAME MOT_LOGGER_FULL_NAME

/* * @define LOGGER_LEVEL The log level of the current logger. */
#define HTAP_LOGGER_LEVEL MOT_LOGGER_LEVEL

/* * @define LOGGER_NAME The name of the current logger. */
#define HTAP_LOGGER_NAME MOT_LOGGER_NAME

/* * @define LOGGER_COMPONENT_NAME The name of the component to which the current logger belongs. */
#define HTAP_LOGGER_COMPONENT_NAME MOT_LOGGER_COMPONENT_NAME

// Severity Levels
/**
 * @define Normal severity level. Some operation failed, but nevertheless the status of HTAP system
 * and the current session is still fine (e.g. transaction aborted due to conflict or unique
 * violation). No action is required by the user.
 */
#define HTAP_SEVERITY_NORMAL MOT_SEVERITY_NORMAL

/**
 * @define Warning severity level. Some operation failed. The status of the HTAP system is fine. The
 * current session can continue to operate, but severity is higher (e.g. configuration file is
 * missing, but the engine can operate with defaults). The user should note the HTAP system condition
 * and might fix it.
 */
#define HTAP_SEVERITY_WARN MOT_SEVERITY_WARN

/**
 * @define Error severity level. Indicates that an operation failed. This is a real error condition
 * that prevents form the current transaction to continue. The current session may continue if error
 * is acceptable and can be handled. Action is required by the envelope (usually report to the user
 * which operation failed and why).
 */
#define HTAP_SEVERITY_ERROR MOT_SEVERITY_ERROR

/* * @define Fatal severity level. Indicates that the HTAP system is inoperable. */
#define HTAP_SEVERITY_FATAL MOT_SEVERITY_FATAL

using HTAPLogSinkType = MOT::MotLogSinkType;

// Log sink
using HTAPWriteToLogSinkFunc = MOT::MOTWriteToLogSinkFunc;
using HTAPFormatToLogSinkFunc = MOT::MOTFormatToLogSinkFunc;
using HTAPFlushLogSinkFunc = MOT::MOTFlushLogSinkFunc;
using HTAPLogSink = MOT::MOTLogSink;

/**
 * @brief Retrieves the log level of all loggers belonging to a specific component.
 * @param componentName The name of the component.
 * @return The log level of the component.
 */
inline LogLevel GetLogComponentLogLevel(const char *componentName)
{
    return MOT::GetLogComponentLogLevel(componentName);
}

/**
 * @brief Retrieves the log level of a specific logger.
 * @param componentName The name of the component to which the logger belongs.
 * @param loggerName The name of the logger to configure its log level.
 * @return The log level of the logger.
 */
inline LogLevel GetLoggerLogLevel(const char *componentName, const char *loggerName)
{
    return MOT::GetLoggerLogLevel(componentName, loggerName);
}

/**
 * @brief Sets the log level of all loggers belonging to a specific component. To be called when configuration changes.
 * @param componentName The name of the component.
 * @param logLevel The new log level.
 * @return The previous log level of the component.
 */
inline LogLevel SetLogComponentLogLevel(const char *componentName, LogLevel logLevel)
{
    return MOT::SetLogComponentLogLevel(componentName, logLevel);
}

/**
 * @brief Sets the log level of a specific logger. To be called when configuration changes.
 * @param componenetName The name of the component to which the logger belongs.
 * @param loggerName The name of the logger to configure its log level.
 * @param logLevel The new log level.
 * @return The previous log level of the logger.
 */
inline LogLevel SetLoggerLogLevel(const char *componenetName, const char *loggerName, LogLevel logLevel)
{
    return MOT::SetLoggerLogLevel(componenetName, loggerName, logLevel);
}

/** @brief Converts string to log level constant. */
inline LogLevel LogLevelFromString(const char *logLevelStr)
{
    return MOT::LogLevelFromString(logLevelStr);
}

/** @brief Converts log level constant to string. */
inline const char *LogLevelToString(LogLevel logLevel)
{
    return MOT::LogLevelToString(logLevel);
}

/** @brief Validates the log level string. */
inline bool ValidateLogLevel(const char *logLevelStr)
{
    return MOT::ValidateLogLevel(logLevelStr);
}

/** @brief Retrieves the currently configured log sink. */
inline HTAPLogSinkType GetLogSinkType()
{
    return MOT::GetLogSinkType();
}

/** @brief Configures the log sink. */
inline void SetLogSink(HTAPLogSinkType logSinkType, HTAPLogSink *logSink = nullptr)
{
    return MOT::SetLogSink(logSinkType, logSink);
}

/** @brief Configures the log sink to use a file stream. */
inline void SetFileLogSink(FILE *fileLogSink)
{
    return MOT::SetFileLogSink(fileLogSink);
}

/** @var The global log level. */
extern LogLevel g_htapGlobalLogLevel;

/**
 * @brief Configures the global log level.
 * @param logLevel The log level to set.
 * @return The previous global log level.
 */
inline LogLevel SetGlobalLogLevel(LogLevel logLevel)
{
    LogLevel prevLogLevel = g_htapGlobalLogLevel;
    g_htapGlobalLogLevel = logLevel;
    return prevLogLevel;
}

/** @brief Retrieves the current global log level. */
inline LogLevel GetGlobalLogLevel()
{
    return g_htapGlobalLogLevel;
}

/**
 * @brief Queries whether a log level qualifies for printing.
 * @details A log level qualifies for printing if it passes three qualification tests, the global log level, the log
 * level of the current thread , and the log level of the reporting component.
 * @param logLevel The log level to check.
 * @param componentLogLevel The reporting component.
 * @return True if the log level qualifies.
 */
inline bool CheckLogLevel(LogLevel logLevel, LogLevel componentLogLevel)
{
    return MOT::CheckLogLevel(logLevel, componentLogLevel);
}

/**
 * @brief Queries whether a log level of a logger is sufficient for printing.
 * @param logLevel The log level limit.
 * @param loggerLogLevel The log level of the logger to check.
 * @return True if the log level of the logger is sufficient for printing.
 */
inline bool CheckLogLevelInline(LogLevel logLevel, LogLevel loggerLogLevel)
{
    return ((logLevel <= g_htapGlobalLogLevel) || (logLevel <= loggerLogLevel));
}

/**
 * @brief Print message to log
 * @param logLevel The log level.
 * @param loggerName The logging entity name.
 * @param format The formatted messages.
 * @param args Additional arguments required by the formatted message.
 */
inline void HTAPLogV(LogLevel logLevel, const char *loggerName, const char *format, va_list args)
{
    MOT::MOTLogV(logLevel, loggerName, format, args);
}

/**
 * @brief Print message to log
 * @param logLevel The log level.
 * @param loggerName The logging entity name.
 * @param format The formatted messages.
 * @param args Additional arguments required by the formatted message.
 */
inline void HTAPLogExV(LogLevel logLevel, const char *loggerName, const char *format, va_list args)
{
    MOT::MOTLogExV(logLevel, loggerName, format, args);
}

/**
 * @brief Print message to log
 * @param logLevel The log level.
 * @param loggerName The logging entity name.
 * @param format The formatted messages.
 * @param ... Additional arguments required by the formatted message.
 */
inline void HTAPLog(LogLevel logLevel, const char *loggerName, const char *format, ...)
{
    va_list args;
    va_start(args, format);

    HTAPLogV(logLevel, loggerName, format, args);

    va_end(args);
}

/**
 * @brief Print message to log
 * @param logLevel The log level.
 * @param loggerName The logging entity name.
 * @param format The formatted messages.
 * @param ... Additional arguments required by the formatted message.
 */
inline void HTAPLogEx(LogLevel logLevel, const char *loggerName, const char *format, ...)
{
    va_list args;
    va_start(args, format);

    HTAPLogExV(logLevel, loggerName, format, args);

    va_end(args);
}

/**
 * @brief Begins a continued printing sequence. A full prefix and initial message formatting is
 * emitted to log, but without setting a trailing newline.
 * @param logLevel The report log level.
 * @param loggerName The name of the logger.
 * @param format The format message.
 * @param args Additional arguments required by the formatted message.
 */
inline void HTAPLogBeginV(LogLevel logLevel, const char *loggerName, const char *format, va_list args)
{
    MOT::MOTLogBeginV(logLevel, loggerName, format, args);
}

/**
 * @brief Begins a continued printing sequence. A full prefix and initial message formatting is
 * emitted to log, but without setting a trailing newline.
 * @param logLevel The report log level.
 * @param loggerName The name of the logger.
 * @param format The format message.
 * @param ... Any additional format message parameters.
 */
inline void HTAPLogBegin(LogLevel logLevel, const char *loggerName, const char *format, ...)
{
    va_list args;
    va_start(args, format);

    MOT::MOTLogBeginV(logLevel, loggerName, format, args);

    va_end(args);
}

/** @brief Appends a message to a continued printing sequence. */
inline void HTAPLogAppendV(const char *format, va_list args)
{
    MOT::MOTLogAppendV(format, args);
}

/** @brief Appends a message to a continued printing sequence. */
inline void HTAPLogAppend(const char *format, ...)
{
    va_list args;
    va_start(args, format);

    HTAPLogAppendV(format, args);

    va_end(args);
}

/** @brief Terminates a continued printing sequence. */
inline void HTAPLogEnd()
{
    MOT::MOTLogEnd();
}

/**
 * @brief Utility function for printing last system error encountered by the current
 * thread.
 * The final message format is as follows:
 * `<FORMATTED_USER_MESSAGE>: <SYSTEM_MESSAGE> (error code: <LAST_ERROR_CODE>)`
 * @param logLevel The error message log level.
 * @param syscall The system call that failed.
 * @param loggerName The name of the logger.
 * @param format A user message to print.
 * @param args Additional arguments required by the formatted message.
 */
inline void HTAPLogSystemErrorV(LogLevel logLevel, const char *syscall, const char *loggerName, const char *format,
    va_list args)
{
    MOT::MOTLogSystemErrorV(logLevel, syscall, loggerName, format, args);
}

/**
 * @brief Utility function for printing last system error encountered by the current
 * thread.
 * The final message format is as follows:
 * `<FORMATTED_USER_MESSAGE>: <SYSTEM_MESSAGE> (error code: <LAST_ERROR_CODE>)`
 * @param logLevel The error message log level.
 * @param syscall The system call that failed.
 * @param loggerName The name of the logger.
 * @param format A user message to print.
 * @param ... Any additional extra arguments to the format message.
 */
inline void HTAPLogSystemError(LogLevel logLevel, const char *syscall, const char *loggerName, const char *format, ...)
{
    va_list args;
    va_start(args, format);

    HTAPLogSystemErrorV(logLevel, syscall, loggerName, format, args);

    va_end(args);
}

/**
 * @brief Utility function for printing last system error encountered by the current
 * thread.
 * The final message format is as follows:
 * `<FORMATTED_USER_MESSAGE>: <SYSTEM_MESSAGE> (error code: <PROVIDED_ERROR_CODE>)`
 * @param logLevel The error message log level.
 * @param rc The error code to print.
 * @param syscall The system call that failed.
 * @param loggerName The name of the logger.
 * @param format A user message to print.
 * @param args Additional arguments required by the formatted message.
 */
inline void HTAPLogSystemErrorCodeV(LogLevel logLevel, int rc, const char *syscall, const char *loggerName,
    const char *format, va_list args)
{
    MOT::MOTLogSystemErrorCodeV(logLevel, rc, syscall, loggerName, format, args);
}

/**
 * @brief Utility function for printing last system error encountered by the current
 * thread.
 * The final message format is as follows:
 * `<FORMATTED_USER_MESSAGE>: <SYSTEM_MESSAGE> (error code: <PROVIDED_ERROR_CODE>)`
 * @param logLevel The error message log level.
 * @param rc The error code to print.
 * @param syscall The system call that failed.
 * @param loggerName The name of the logger.
 * @param format A user message to print.
 * @param ... Any additional extra arguments to the format message.
 */
inline void HTAPLogSystemErrorCode(LogLevel logLevel, int rc, const char *syscall, const char *loggerName,
    const char *format, ...)
{
    va_list args;
    va_start(args, format);

    HTAPLogSystemErrorCodeV(logLevel, rc, syscall, loggerName, format, args);

    va_end(args);
}

/**
 * @brief Utility function for printing call stack of the current thread.
 * @param logLevel The message log level.
 * @param loggerName The name of the logger.
 * @param opts Call stack printing options (see debug_utils.h for definitions).
 * @param format A user message to print.
 * @param args Additional arguments required by the formatted message.
 */
inline void HTAPPrintCallStackV(LogLevel logLevel, const char *loggerName, int opts, const char *format, va_list args)
{
    MOT::MOTPrintCallStackV(logLevel, loggerName, opts, format, args);
}

/**
 * @brief Utility function for printing call stack of the current thread.
 * @param logLevel The message log level.
 * @param loggerName The name of the logger.
 * @param opts Call stack printing options (see debug_utils.h for definitions).
 * @param format A user message to print.
 * @param ... Any additional extra arguments to the format message.
 */
inline void HTAPPrintCallStack(LogLevel logLevel, const char *loggerName, int opts, const char *format, ...)
{
    va_list args;
    va_start(args, format);

    HTAPPrintCallStackV(logLevel, loggerName, opts, format, args);

    va_end(args);
}

/**
 * @brief Sets the last error code for the current thread.
 * @param errorCode The error code to set.
 * @param severity The error severity.
 */
inline void SetLastError(RC errorCode, int severity)
{
    MOT::SetLastErrorEx((int)errorCode, severity, MOD_HTAP);
}

/**
 * @brief Retrieves the last error reported by the current thread.
 * @return The last error code reported by this thread.
 */
inline RC GetLastError()
{
    return (RC)MOT::GetLastError();
}

/**
 * @brief Retrieves the severity of the last error reported by the current thread.
 * @return The last error code severity reported by this thread.
 */
inline int GetLastErrorSeverity()
{
    return MOT::GetLastErrorSeverity();
}

/**
 * @brief Retrieves the id of the module who emitted the last error reported by the current thread.
 * @return The module id who reported the last error for the current thread.
 */
inline int GetLastErrorModule()
{
    return MOT::GetLastErrorModule();
}

/**
 * @brief Retrieves the root error reported by the current thread. The root error is the first one
 * reported since the last call to @ref ClearErrorStack().
 * @return The root error code reported by this thread.
 */
inline RC GetRootError()
{
    return (RC)MOT::GetRootError();
}

/**
 * @brief Retrieves the root error severity reported by the current thread. The root error severity
 * is the first one reported since the last call to @ref ClearErrorStack().
 * @return The root error code reported by this thread.
 */
inline int GetRootErrorSeverity()
{
    return MOT::GetRootErrorSeverity();
}

/**
 * @brief Retrieves the root error module reported by the current thread.
 * @return The root error module reported by this thread.
 */
inline int GetRootErrorModule()
{
    return MOT::GetRootErrorModule();
}

/**
 * @brief Converts error severity to string.
 * @param severity The error severity to translate.
 * @return The textual representation of the error code.
 */
inline const char *SeverityToString(int severity)
{
    return MOT::SeverityToString(severity);
}

/**
 * @brief Push error report on the error stack. Do not call this method directly, but rather use the
 * utility macro @ref MOT_PUSH_ERROR().
 * @param errorCode The error code to report.
 * @param severity The error severity.
 * @param file The reporting file.
 * @param line The reporting line.
 * @param function The reporting function.
 * @param entity The reporting entity.
 * @param context The report context.
 * @param format The error message format.
 * @param args Additional arguments for the error message.
 */
inline void PushErrorV(RC errorCode, int severity, const char *file, int line, const char *function, const char *entity,
    const char *context, const char *format, va_list args)
{
    MOT::PushErrorExV((int)errorCode, severity, MOD_HTAP, file, line, function, entity, context, format, args);
}

/**
 * @brief Push error report on the error stack. Do not call this method directly, but rather use the
 * utility macro @ref MOT_PUSH_ERROR().
 * @param errorCode The error code to report.
 * @param severity The error severity.
 * @param file The reporting file.
 * @param line The reporting line.
 * @param function The reporting function.
 * @param entity The reporting entity.
 * @param context The report context.
 * @param format The error message format.
 * @param ... Additional arguments for the error message.
 */
inline void PushError(RC errorCode, int severity, const char *file, int line, const char *function, const char *entity,
    const char *context, const char *format, ...)
{
    va_list args;
    va_start(args, format);

    PushErrorV(errorCode, severity, file, line, function, entity, context, format, args);

    va_end(args);
}

/**
 * @brief Push error report on the error stack. Do not call this method directly, but rather use the
 * utility macro @ref MOT_PUSH_ERROR().
 * @param errorCode The error code to report.
 * @param severity The error severity.
 * @param file The reporting file.
 * @param line The reporting line.
 * @param function The reporting function.
 * @param entity The reporting entity.
 * @param context The report context.
 * @param systemCall The failing system call.
 */
inline void PushSystemError(int errorCode, int severity, const char *file, int line, const char *function,
    const char *entity, const char *context, const char *systemCall)
{
    MOT::PushSystemError(errorCode, severity, file, line, function, entity, context, systemCall);
}

/**
 * @brief Prints the error stack.
 * @see PushError().
 */
inline void PrintErrorStack()
{
    MOT::PrintErrorStack();
}

/**
 * @brief Clears the error stack.
 * @see PushError().
 */
inline void ClearErrorStack()
{
    MOT::ClearErrorStack();
}
} // namespace htap

/* * @define Utility macro for checking whether the log level of the current logger is sufficient for printing. */
#define HTAP_CHECK_LOG_LEVEL(logLevel) htap::CheckLogLevelInline(logLevel, HTAP_LOGGER_LEVEL)

/* * @define Utility macro for checking whether the current logger can print TRACE-level messages. */
#define HTAP_CHECK_TRACE_LOG_LEVEL() HTAP_CHECK_LOG_LEVEL(htap::LogLevel::LL_TRACE)

/* * @define Utility macro for checking whether the current logger can print DEBUG-level messages. */
#define HTAP_CHECK_DEBUG_LOG_LEVEL() HTAP_CHECK_LOG_LEVEL(htap::LogLevel::LL_DEBUG)

/* * @define Utility macro for checking whether the current logger can print DIAG1-level messages. */
#define HTAP_CHECK_DIAG1_LOG_LEVEL() HTAP_CHECK_LOG_LEVEL(htap::LogLevel::LL_DIAG1)

/* * @define Utility macro for checking whether the current logger can print DIAG2-level messages. */
#define HTAP_CHECK_DIAG2_LOG_LEVEL() HTAP_CHECK_LOG_LEVEL(htap::LogLevel::LL_DIAG2)

/* * @define Begins a log printing in continuation. */
#define HTAP_LOG_BEGIN(logLevel, format, ...)                                       \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {                                           \
        htap::HTAPLogBegin(logLevel, HTAP_LOGGER_FULL_NAME, format, ##__VA_ARGS__); \
    }

/* * @define Begins a log printing in continuation. */
#define HTAP_LOG_BEGIN_EX(logLevel, errorNum, format, ...)                          \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {                                           \
        htap::HTAPLogBegin(logLevel, HTAP_LOGGER_FULL_NAME, format, ##__VA_ARGS__); \
        htap::HTAPLogSetErrorNum(errorNum);                                         \
    }

/* * @define Adds a log message to log printing in continuation. */
#define HTAP_LOG_APPEND(logLevel, format, ...)      \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {           \
        htap::HTAPLogAppend(format, ##__VA_ARGS__); \
    }

/* * @define Adds a log message to log printing in continuation. */
#define HTAP_LOG_APPEND_V(logLevel, format, args) \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {         \
        htap::HTAPLogAppendV(format, args);       \
    }

/* * @define Ends a log printing in continuation. */
#define HTAP_LOG_END(logLevel)            \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) { \
        htap::HTAPLogEnd();               \
    }

/* * @define Utility log printing macro. */
#define HTAP_LOG(logLevel, format, ...)                                        \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {                                      \
        htap::HTAPLog(logLevel, HTAP_LOGGER_FULL_NAME, format, ##__VA_ARGS__); \
    }

/* * @define Utility log printing macro. */
#define HTAP_LOG_EX(logLevel, format, ...)                                       \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {                                        \
        htap::HTAPLogEx(logLevel, HTAP_LOGGER_FULL_NAME, format, ##__VA_ARGS__); \
    }

/* * @define Utility PANIC-level log printing macro. */
#define HTAP_LOG_PANIC(format, ...) HTAP_LOG(htap::LogLevel::LL_PANIC, format, ##__VA_ARGS__)

/* * @define Utility ERROR-level log printing macro. */
#define HTAP_LOG_ERROR(format, ...) HTAP_LOG(htap::LogLevel::LL_ERROR, format, ##__VA_ARGS__)

/* * @define Utility WARN-level log printing macro. */
#define HTAP_LOG_WARN(format, ...) HTAP_LOG(htap::LogLevel::LL_WARN, format, ##__VA_ARGS__)

/* * @define Utility INFO-level log printing macro. */
#define HTAP_LOG_INFO(format, ...) HTAP_LOG(htap::LogLevel::LL_INFO, format, ##__VA_ARGS__)

/* * @define Utility TRACE-level log printing macro. */
#define HTAP_LOG_TRACE(format, ...) HTAP_LOG(htap::LogLevel::LL_TRACE, format, ##__VA_ARGS__)

/* * @define Utility DEBUG-level log printing macro. */
#define HTAP_LOG_DEBUG(format, ...) HTAP_LOG(htap::LogLevel::LL_DEBUG, format, ##__VA_ARGS__)

/* * @define Utility DIAG1-level log printing macro. */
#define HTAP_LOG_DIAG1(format, ...) HTAP_LOG(htap::LogLevel::LL_DIAG1, format, ##__VA_ARGS__)

/* * @define Utility DIAG2-level log printing macro. */
#define HTAP_LOG_DIAG2(format, ...) HTAP_LOG(htap::LogLevel::LL_DIAG2, format, ##__VA_ARGS__)

/* * @define Utility PANIC-level log printing macro. */
#define HTAP_LOG_PANIC_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_PANIC, format, ##__VA_ARGS__)

/* * @define Utility ERROR-level log printing macro. */
#define HTAP_LOG_ERROR_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_ERROR, format, ##__VA_ARGS__)

/* * @define Utility WARN-level log printing macro. */
#define HTAP_LOG_WARN_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_WARN, format, ##__VA_ARGS__)

/* * @define Utility INFO-level log printing macro. */
#define HTAP_LOG_INFO_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_INFO, format, ##__VA_ARGS__)

/* * @define Utility TRACE-level log printing macro. */
#define HTAP_LOG_TRACE_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_TRACE, format, ##__VA_ARGS__)

/* * @define Utility DEBUG-level log printing macro. */
#define HTAP_LOG_DEBUG_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_DEBUG, format, ##__VA_ARGS__)

/* * @define Utility DIAG1-level log printing macro. */
#define HTAP_LOG_DIAG1_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_DIAG1, format, ##__VA_ARGS__)

/* * @define Utility DIAG2-level log printing macro. */
#define HTAP_LOG_DIAG2_EX(format, ...) HTAP_LOG_EX(htap::LogLevel::LL_DIAG2, format, ##__VA_ARGS__)

/* * @define Utility log printing macro with variadic va_list argument. */
#define HTAP_LOG_V(logLevel, format, args)                             \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {                              \
        htap::HTAPLogV(logLevel, HTAP_LOGGER_FULL_NAME, format, args); \
    }

/* * @define Utility PANIC-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_PANIC_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_PANIC, format, args)

/* * @define Utility ERROR-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_ERROR_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_ERROR, format, args)

/* * @define Utility WANR-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_WARN_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_WARN, format, args)

/* * @define Utility INFO-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_INFO_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_INFO, format, args)

/* * @define Utility TRACE-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_TRACE_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_TRACE, format, args)

/* * @define Utility DEBUG-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_DEBUG_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_DEBUG, format, args)

/* * @define Utility DIAG1-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_DIAG1_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_DIAG1, format, args)

/* * @define Utility DIAG2-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_DIAG2_V(format, args) HTAP_LOG_V(htap::LogLevel::LL_DIAG2, format, args)

/* * @define Utility log printing macro with variadic va_list argument. */
#define HTAP_LOG_EX_V(logLevel, errorNum, format, args)                            \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {                                          \
        htap::HTAPLogExV(logLevel, HTAP_LOGGER_FULL_NAME, errorNum, format, args); \
    }

/* * @define Utility PANIC-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_PANIC_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_PANIC, errorNum, format, args)

/* * @define Utility ERROR-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_ERROR_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_ERROR, errorNum, format, args)

/* * @define Utility WANR-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_WARN_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_WARN, errorNum, format, args)

/* * @define Utility INFO-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_INFO_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_INFO, errorNum, format, args)

/* * @define Utility TRACE-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_TRACE_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_TRACE, errorNum, format, args)

/* * @define Utility DEBUG-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_DEBUG_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_DEBUG, errorNum, format, args)

/* * @define Utility DIAG1-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_DIAG1_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_DIAG1, errorNum, format, args)

/* * @define Utility DIAG2-level log printing macro with variadic va_list argument. */
#define HTAP_LOG_DIAG2_EX_V(errorNum, format, args) HTAP_LOG_EX_V(htap::LogLevel::LL_DIAG2, errorNum, format, args)

/* * @define Utility log printing macro for failed system call. */
#define HTAP_LOG_SYSTEM(logLevel, syscall, format, ...) \
    htap::HTAPLogSystemError(logLevel, #syscall, HTAP_LOGGER_FULL_NAME, format, ##__VA_ARGS__)

/* * @define Utility log printing macro for failed system call with error code. */
#define HTAP_LOG_SYSTEM_CODE(logLevel, rc, syscall, format, ...) \
    htap::HTAPLogSystemErrorCode(logLevel, rc, #syscall, HTAP_LOGGER_FULL_NAME, format, ##__VA_ARGS__)

/* * @define Utility PANIC-level log printing macro for failed system call. */
#define HTAP_LOG_SYSTEM_PANIC(syscall, format, ...) \
    HTAP_LOG_SYSTEM(htap::LogLevel::LL_PANIC, syscall, format, ##__VA_ARGS__)

/* * @define Utility PANIC-level log printing macro for failed system call with error code. */
#define HTAP_LOG_SYSTEM_PANIC_CODE(rc, syscall, format, ...) \
    HTAP_LOG_SYSTEM_CODE(htap::LogLevel::LL_PANIC, rc, syscall, format, ##__VA_ARGS__)

/* * @define Utility ERROR-level log printing macro for failed system call. */
#define HTAP_LOG_SYSTEM_ERROR(syscall, format, ...) \
    HTAP_LOG_SYSTEM(htap::LogLevel::LL_ERROR, syscall, format, ##__VA_ARGS__)

/* * @define Utility ERROR-level log printing macro for failed system call with error code. */
#define HTAP_LOG_SYSTEM_ERROR_CODE(rc, syscall, format, ...) \
    HTAP_LOG_SYSTEM_CODE(htap::LogLevel::LL_ERROR, rc, syscall, format, ##__VA_ARGS__)

/* * @define Utility WARN-level log printing macro for failed system call. */
#define HTAP_LOG_SYSTEM_WARN(syscall, format, ...) \
    HTAP_LOG_SYSTEM(htap::LogLevel::LL_WARN, syscall, format, ##__VA_ARGS__)

/* * @define Utility WARN-level log printing macro for failed system call with error code. */
#define HTAP_LOG_SYSTEM_WARN_CODE(rc, syscall, format, ...) \
    HTAP_LOG_SYSTEM_CODE(htap::LogLevel::LL_WARN, rc, syscall, format, ##__VA_ARGS__)

/* * @define Utility macro for printing call stack of current thread. */
#define HTAP_PRINT_CALL_STACK(logLevel, opts, format, ...)                                      \
    if (HTAP_CHECK_LOG_LEVEL(logLevel)) {                                                       \
        htap::HTAPPrintCallStack(logLevel, HTAP_LOGGER_FULL_NAME, opts, format, ##__VA_ARGS__); \
    }

/* * @define Utility macro for clearing the last error code for the current thread. */
#define HTAP_CLEAR_LAST_ERROR() htap::SetLastError(HTAP_NO_ERROR, HTAP_SEVERITY_NORMAL)

/* * @define Utility macro for checking the last error code. */
#define HTAP_IS_ERROR(errorCode) (htap::GetLastError() == errorCode)

/* * @define Utility macro for checking if the last error code was "out of memory". */
#define HTAP_IS_OOM() (htap::GetRootError() == HTAP_ERROR_OOM)

/* * @define Utility macro for checking if the current error state represents a severe error. */
#define HTAP_IS_SEVERE() (htap::GetRootErrorSeverity() >= HTAP_SEVERITY_ERROR)

/* * @define Utility macro for pushing error report on the error stack. */
#define HTAP_PUSH_ERROR(errorCode, severity, context, format, ...)                                               \
    htap::PushError(errorCode, severity, __FILE__, __LINE__, __func__, _logger.m_qualifiedName, context, format, \
        ##__VA_ARGS__)

/* * @define Utility macro for pushing error report on the error stack. */
#define HTAP_PUSH_ERROR_V(errorCode, severity, context, format, args) \
    htap::PushErrorV(errorCode, severity, __FILE__, __LINE__, __func__, _logger.m_qualifiedName, context, format, args)

/* * @define Utility macro for pushing system error report on the error stack. */
#define HTAP_PUSH_SYSTEM_ERROR(systemErrorCode, severity, context, systemCall)                                       \
    htap::PushSystemError(systemErrorCode, severity, __FILE__, __LINE__, __func__, _logger.m_qualifiedName, context, \
        #systemCall)

/* * @define Utility helper for printing the error stack (preceded by a formatted message). */
#define HTAP_LOG_ERROR_STACK(format, ...)  \
    HTAP_LOG_ERROR(format, ##__VA_ARGS__); \
    htap::PrintErrorStack();

/* * @define Utility helper for printing the error stack (preceded by a formatted message). */
#define HTAP_LOG_PANIC_STACK(format, ...)  \
    HTAP_LOG_PANIC(format, ##__VA_ARGS__); \
    htap::PrintErrorStack();

/* * @define Utility macro for pushing error report on the error stack. */
#define HTAP_REPORT_ERROR(errorCode, context, format, ...) \
    HTAP_LOG_ERROR(format, ##__VA_ARGS__);                 \
    HTAP_PUSH_ERROR(errorCode, HTAP_SEVERITY_ERROR, context, format, ##__VA_ARGS__)

/* * @define Utility macro for pushing error report on the error stack. */
#define HTAP_REPORT_PANIC(errorCode, context, format, ...) \
    HTAP_LOG_PANIC(format, ##__VA_ARGS__);                 \
    HTAP_PUSH_ERROR(errorCode, HTAP_SEVERITY_FATAL, context, format, ##__VA_ARGS__)

/* * @define Utility macro for pushing error report on the error stack. */
#define HTAP_REPORT_ERROR_V(errorCode, context, format, args) \
    HTAP_LOG_ERROR_V(format, args);                           \
    HTAP_PUSH_ERROR_V(errorCode, HTAP_SEVERITY_ERROR, context, format, args)

/* * @define Utility macro for pushing error report on the error stack. */
#define HTAP_REPORT_PANIC_V(errorCode, context, format, args) \
    HTAP_LOG_PANIC_V(format, args);                           \
    HTAP_PUSH_ERROR_V(errorCode, HTAP_SEVERITY_FATAL, context, format, args)

/* * @define Utility helper for reporting system call failure (with error code). */
#define HTAP_REPORT_SYSTEM_ERROR_CODE(systemErrorCode, systemCall, context, format, ...) \
    HTAP_LOG_SYSTEM_ERROR_CODE(systemErrorCode, systemCall, format, ##__VA_ARGS__);      \
    HTAP_PUSH_SYSTEM_ERROR(systemErrorCode, HTAP_SEVERITY_ERROR, context, systemCall);   \
    HTAP_PUSH_ERROR(HTAP_ERROR_SYSTEM_FAILURE, HTAP_SEVERITY_ERROR, context, format, ##__VA_ARGS__);

/* * @define Utility helper for reporting system call failure (with error code). */
#define HTAP_REPORT_SYSTEM_PANIC_CODE(systemErrorCode, systemCall, context, format, ...) \
    HTAP_LOG_SYSTEM_PANIC_CODE(systemErrorCode, systemCall, format, ##__VA_ARGS__);      \
    HTAP_PUSH_SYSTEM_ERROR(systemErrorCode, HTAP_SEVERITY_FATAL, context, systemCall);   \
    HTAP_PUSH_ERROR(HTAP_ERROR_SYSTEM_FAILURE, HTAP_SEVERITY_FATAL, context, format, ##__VA_ARGS__);

/* * @define Utility helper for reporting system call failure (with error code). */
#define HTAP_REPORT_SYSTEM_ERROR(systemCall, context, format, ...) \
    HTAP_REPORT_SYSTEM_ERROR_CODE(errno, systemCall, context, format, ##__VA_ARGS__)

/* * @define Utility helper for reporting system call failure (with error code). */
#define HTAP_REPORT_SYSTEM_PANIC(systemCall, context, format, ...) \
    HTAP_REPORT_SYSTEM_PANIC_CODE(errno, systemCall, context, format, ##__VA_ARGS__)

#endif // HTAP_LOGGER_H
